package com.zhiche.wms.service.outbound.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.baomidou.mybatisplus.plugins.Page;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.google.common.collect.Maps;
import com.zhiche.wms.core.supports.BaseException;
import com.zhiche.wms.core.supports.enums.TableStatusEnum;
import com.zhiche.wms.core.utils.SnowFlakeId;
import com.zhiche.wms.domain.mapper.outbound.OutboundKeyPrepareHeaderMapper;
import com.zhiche.wms.domain.mapper.outbound.OutboundKeyPrepareLineMapper;
import com.zhiche.wms.domain.mapper.outbound.OutboundNoticeHeaderMapper;
import com.zhiche.wms.domain.mapper.outbound.OutboundPrepareHeaderMapper;
import com.zhiche.wms.domain.mapper.stock.StockMapper;
import com.zhiche.wms.domain.model.base.StoreLocation;
import com.zhiche.wms.domain.model.outbound.*;
import com.zhiche.wms.domain.model.stock.Sku;
import com.zhiche.wms.domain.model.stock.Stock;
import com.zhiche.wms.domain.model.sys.User;
import com.zhiche.wms.dto.outbound.*;
import com.zhiche.wms.service.base.IBusinessDocNumberService;
import com.zhiche.wms.service.base.IStoreLocationService;
import com.zhiche.wms.service.outbound.*;
import com.zhiche.wms.service.stock.ISkuService;
import com.zhiche.wms.service.stock.IStockService;
import com.zhiche.wms.service.sys.IUserService;
import com.zhiche.wms.service.utils.CommonMethod;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.assertj.core.util.Lists;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * <p>
 * 出库备料单头 服务实现类
 * </p>
 *
 * @author zhaoguixin
 * @since 2018-06-27
 */
@Service
public class OutboundPrepareHeaderServiceImpl extends ServiceImpl<OutboundPrepareHeaderMapper, OutboundPrepareHeader> implements IOutboundPrepareHeaderService {

    private static final Logger LOGGER = LoggerFactory.getLogger(OutboundPrepareHeaderServiceImpl.class);

    @Autowired
    private IUserService userService;
    @Autowired
    private IOutboundNoticeLineService noticeLineService;
    @Autowired
    private IOutboundNoticeHeaderService noticeHeaderService;
    @Autowired
    private OutboundNoticeHeaderMapper outboundNoticeHeaderMapper;
    @Autowired
    private IOutboundPrepareLineService prepareLineService;
    @Autowired
    private IOutboundKeyPrepareLineService keyPrepareLineService;
    @Autowired
    private OutboundKeyPrepareHeaderMapper keyPrepareHeaderMapper;
    @Autowired
    private SnowFlakeId snowFlakeId;
    @Autowired
    private IBusinessDocNumberService docNumberService;
    @Autowired
    private IStockService stockService;
    @Autowired
    private IStoreLocationService locationService;
    @Autowired
    private ISkuService skuService;
    @Autowired
    private OutboundKeyPrepareLineMapper keyPrepareLineMapper;
    @Autowired
    private IOutboundShipLineService shipLineService;
    @Autowired
    private StockMapper stockMapper;


    public Integer updateStatus(Long id, Long houseId, Integer status, BigDecimal damagedSum) {
        return this.baseMapper.updateStatus(id, houseId, status, damagedSum);
    }

    /**
     * 查询备料任务列表  关联通知单头/明细  出库单头/明细
     */
    @Override
    public Page<PreparationListHeadDTO> queryOutPreparePage(Page<PreparationListHeadDTO> page) {
        Wrapper<PreparationListHeadDTO> wp = buildWrapper(page, TableStatusEnum.STATUS_0.getCode());
        List<PreparationListHeadDTO> records = baseMapper.queryOutPreparePage(page, wp);
        page.setRecords(records);
        return page;
    }

    private Wrapper<PreparationListHeadDTO> buildWrapper(Page<PreparationListHeadDTO> page, String is) {
        if (page == null) {
            throw new BaseException("参数不能为空");
        }
        Wrapper<PreparationListHeadDTO> wp = new EntityWrapper<>();
        Map cd = page.getCondition();
        if (cd != null) {
            if (Objects.nonNull(cd.get("storeHouseId")) && StringUtils.isNotBlank(cd.get("storeHouseId").toString())) {
                wp.eq("houseId", cd.get("storeHouseId").toString());
            }
            if (TableStatusEnum.STATUS_0.getCode().equals(is)) {
                if (Objects.nonNull(cd.get("preparationStatus")) && StringUtils.isNotBlank(cd.get("preparationStatus").toString())) {
                    wp.eq("prepareStatus", cd.get("preparationStatus").toString());
                }
            }
            if (Objects.nonNull(cd.get("ownerOrderNo")) && StringUtils.isNotBlank(cd.get("ownerOrderNo").toString())) {
                wp.eq("owner_order_no", cd.get("ownerOrderNo").toString());
            }
            if (Objects.nonNull(cd.get("outShipStatus")) && StringUtils.isNotBlank(cd.get("outShipStatus").toString())) {
                wp.eq("noticeHeadStatus", cd.get("outShipStatus").toString());
            }
            if (Objects.nonNull(cd.get("startDate")) && StringUtils.isNotEmpty((String) cd.get("startDate"))) {
                wp.ge("shipmentCreate", cd.get("startDate").toString());
            }
            if (Objects.nonNull(cd.get("endDate")) && StringUtils.isNotEmpty((String) cd.get("endDate"))) {
                wp.le("shipmentCreate", cd.get("endDate").toString());
            }
            if (Objects.nonNull(cd.get("providerName")) && StringUtils.isNotEmpty((String) cd.get("providerName"))) {
                wp.like("service_provider_name", cd.get("providerName").toString());
            }

            if (Objects.nonNull(cd.get("lotNo1")) && StringUtils.isNotBlank(cd.get("lotNo1").toString())) {
                EntityWrapper<OutboundNoticeLine> nlEW = new EntityWrapper<>();
                String vin = cd.get("lotNo1").toString();
                List<String> vins = Arrays.asList(CommonMethod.setVins(vin));
                nlEW.ne("status", TableStatusEnum.STATUS_50.getCode());
                nlEW.andNew().in("lot_no1", vins).or().like("lot_no1", vin);
                List<OutboundNoticeLine> noticeLines = noticeLineService.selectList(nlEW);
                ArrayList<Long> ids = Lists.newArrayList();
                for (OutboundNoticeLine line : noticeLines) {
                    ids.add(line.getHeaderId());
                }
                wp.in("noticeHeadId", ids);
            }
        }
        if (TableStatusEnum.STATUS_1.getCode().equals(is)) {
            wp.groupBy("owner_order_no");
        }
        wp.orderBy("shipmentCreate", Boolean.FALSE).orderBy("owner_order_no", Boolean.TRUE);
        return wp;
    }


    /**
     * 保存备料单
     */
    @Override
    public void createPreparation(OutboundPreparationParamDTO dto) {
        if (dto == null) {
            throw new BaseException("参数不能为空!");
        }
        String noticeHeadId = dto.getNoticeHeadId();
        String planTime = dto.getPlanTime();
        String prepareLane = dto.getPrepareLane();
        if (StringUtils.isBlank(prepareLane)) {
            throw new BaseException("请填写备料装车道");
        }
        if (StringUtils.isBlank(planTime)) {
            throw new BaseException("计划备料时间不能为空");
        }
        if (StringUtils.isBlank(noticeHeadId)) {
            throw new BaseException("请选择需要创建备料任务的数据");
        }
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date pt = null;
        try {
            pt = sdf.parse(planTime);
        } catch (ParseException e) {
            throw new BaseException("日期" + dto.getPlanTime() + "转换异常");
        }

        User loginUser = userService.getLoginUser();
        if (loginUser == null) {
            throw new BaseException("请登录后进行该操作");
        }

        //车辆出库备料
        this.outBoundPrepare(noticeHeadId, prepareLane, loginUser, pt);

        //钥匙备料
        this.keyPrepare(noticeHeadId, prepareLane, loginUser, pt);
    }

    /**
     * 车辆出库备料
     *
     * @param noticeHeadId 投标id
     * @param prepareLane  备料时间
     * @param loginUser    登录用户
     * @param pt           时间
     */
    private void outBoundPrepare(String noticeHeadId, String prepareLane, User loginUser, Date pt) {
        OutboundNoticeHeader noticeHeader = noticeHeaderService.selectById(noticeHeadId);

        //限制向塘铁运库A库的装车道为：1,2,9 hgy 20200824
        if ("203284931621679104".equals(Long.toString(noticeHeader.getStoreHouseId()))){
            if (!"1".equals(prepareLane.trim()) && !"2".equals(prepareLane.trim()) && !"9".equals(prepareLane.trim())){
                throw new BaseException("向塘铁运库A库的装车道只能是：1,2,9");
            }
        }

        //校验重复性
        EntityWrapper<OutboundPrepareHeader> wrapper = new EntityWrapper<>();
        wrapper.in("notice_id", noticeHeadId);
        int count = selectCount(wrapper);
        if (count > 0) {
            throw new BaseException("请继续单台备料操作");
        }
        EntityWrapper<OutboundNoticeLine> nlw = new EntityWrapper<>();
        nlw.eq("header_id", noticeHeadId)
                .eq("status", TableStatusEnum.STATUS_10.getCode());
        List<OutboundNoticeLine> noticeLines = noticeLineService.selectList(nlw);
        if (CollectionUtils.isEmpty(noticeLines)) {
            throw new BaseException("未查询到对应出库通知单信息");
        }
        ArrayList<OutboundPrepareLine> ipls = Lists.newArrayList();
        OutboundPrepareHeader ph = savePreparationHead(loginUser, pt, noticeHeader);
        ph.setPlanSumQty(new BigDecimal(0));
        ph.setLineCount(0);
        ph.setLoadingArea(prepareLane);
        for (OutboundNoticeLine noticeLine : noticeLines) {
            //查询库存
            Integer stockCount = stockMapper.queryStockPrepare(noticeLine.getLotNo1(), noticeHeader.getStoreHouseId());
            if (stockCount == 0) {
                throw new BaseException("未查询到车架号:" + noticeLine.getLotNo1() + "库存信息");
            }

            List<StockSkuToPrepareDTO> list = stockService.selectStockToPrepareByParams(noticeLine, noticeHeader.getStoreHouseId());
            if (CollectionUtils.isEmpty(list)) {
                EntityWrapper<OutboundNoticeHeader> hEw = new EntityWrapper<>();
                hEw.eq("opl.lot_no1", noticeLine.getLotNo1());
                hEw.eq("onh.store_house_id", noticeHeader.getStoreHouseId());
                hEw.isNotNull("opl.id");
                List<OutboundNoticeHeader> outboundNoticeHeader = outboundNoticeHeaderMapper.queryPrepareShipment(hEw);
                if (CollectionUtils.isNotEmpty(outboundNoticeHeader)) {
                    throw new BaseException("车辆［" + noticeLine.getLotNo1() + "］曾经在指令［" + outboundNoticeHeader.get(0).getSourceKey() + "] " +
                            "中备料未出库，请在“已备料列表”中根据指令号查询后对该车辆操作“备料任务变更“");
                }else {
                    throw new BaseException("车辆［" + noticeLine.getLotNo1() + "］已有备料信息，请在“已备料列表”中根据指令号查询后对该车辆操作“备料任务变更“");
                }
            }
            StockSkuToPrepareDTO stockSkuToPrepareDTO = list.get(0);
            if ((stockSkuToPrepareDTO.getRemainQty().compareTo(noticeLine.getExpectQty())) < 0) {
                throw new BaseException("车架号" + noticeLine.getLotNo1() + "库存不足通知单数量出库");
            }
            OutboundPrepareLine pl = savePreparationLine(loginUser, pt, noticeLine, ph, stockSkuToPrepareDTO);
            pl.setShipSpace(prepareLane);
            ph.setPlanSumQty(ph.getPlanSumQty().add(pl.getPlanQty()));
            ph.setLineCount(ph.getLineCount() + 1);
            ipls.add(pl);
        }
        //头
        if (CollectionUtils.isNotEmpty(ipls)) {
            insert(ph);
            for (OutboundPrepareLine outboundPrepareLine :ipls){
                prepareLineService.insert(outboundPrepareLine);
            }
        }
    }

    /**
     * 钥匙备料数据
     *
     * @param noticeHeadId 详单id
     * @param prepareLane  备料计划车道
     * @param loginUser    登录用户
     * @param pt           备料时间
     */
    private void keyPrepare(String noticeHeadId, String prepareLane, User loginUser, Date pt) {
        OutboundNoticeHeader noticeHeader = noticeHeaderService.selectById(noticeHeadId);
        //校验重复性
        EntityWrapper<OutboundKeyPrepareHeader> wrapper = new EntityWrapper<>();
        wrapper.in("notice_id", noticeHeadId);
        int count = keyPrepareHeaderMapper.selectCount(wrapper);
        if (count > 0) {
            throw new BaseException("请继续单台备料操作");
        }
        EntityWrapper<OutboundNoticeLine> nlw = new EntityWrapper<>();
        nlw.eq("header_id", noticeHeadId).eq("status", TableStatusEnum.STATUS_10.getCode());
        List<OutboundNoticeLine> noticeLines = noticeLineService.selectList(nlw);
        if (CollectionUtils.isEmpty(noticeLines)) {
            throw new BaseException("未查询到对应的的出库通知单信息");
        }
        ArrayList<OutboundKeyPrepareLine> ipls = Lists.newArrayList();
        OutboundKeyPrepareHeader ph = saveKeyPreparationHead(loginUser, pt, noticeHeader);
        ph.setPlanSumQty(new BigDecimal(0));
        ph.setLineCount(0);
        ph.setLoadingArea(prepareLane);
        for (OutboundNoticeLine noticeLine : noticeLines) {
            OutboundKeyPrepareLine pl = saveKeyPreparationLine(pt, noticeLine, ph, loginUser);
            pl.setShipSpace(prepareLane);
            ph.setPlanSumQty(ph.getPlanSumQty().add(pl.getPlanQty()));
            ph.setLineCount(ph.getLineCount() + 1);
            ipls.add(pl);
        }
        //头
        if (CollectionUtils.isNotEmpty(ipls)) {
            keyPrepareHeaderMapper.insert(ph);
            keyPrepareLineService.insertBatch(ipls);
        }
    }

    private OutboundKeyPrepareLine saveKeyPreparationLine(Date finalPt, OutboundNoticeLine nl, OutboundKeyPrepareHeader ph, User loginUser) {
        OutboundKeyPrepareLine pl = new OutboundKeyPrepareLine();
        BeanUtils.copyProperties(nl, pl);
        pl.setId(snowFlakeId.nextId());
        pl.setHeaderId(ph.getId());
        pl.setNoticeLineId(nl.getId());
        pl.setPlanQty(nl.getExpectQty());
        pl.setActualQty(new BigDecimal("0"));
        pl.setPreparetor(loginUser.getName());
        pl.setPlanTime(finalPt);
        pl.setStatus(TableStatusEnum.STATUS_10.getCode());
        return pl;
    }

    /**
     * 根据noticeHeadId获取详细信息
     */
    @Override
    public List<PreparationListDetailDTO> getPreparationDetail(OutboundPreparationParamDTO dto) {
        if (dto == null) {
            throw new BaseException("参数不能为空");
        }
        String noticeHeadId = dto.getNoticeHeadId();
        if (StringUtils.isBlank(noticeHeadId)) {
            throw new BaseException("通知单id不能为空");
        }
        HashMap<String, Object> params = Maps.newHashMap();
        params.put("noticeHeadId", noticeHeadId);
        params.put("headId", dto.getHeadId());
        params.put("groupBy", "lineId");
        params.put("orderBy", "a.gmt_modified desc");
        baseMapper.updateSQLMode();
        List<PreparationListDetailDTO> detailDTOS = baseMapper.selectPreparationDetailListByParams(params);
        List<PreparationListDetailDTO> resluts = new ArrayList<>();
        if (StringUtils.isBlank(dto.getHeadId())) {
            for (PreparationListDetailDTO detailDTO : detailDTOS) {
                Wrapper<OutboundPrepareLine> outboundPrepareLineWrapper = new EntityWrapper<>();
                outboundPrepareLineWrapper.eq("notice_line_id", detailDTO.getLineId());
                OutboundPrepareLine outboundPrepareLine = prepareLineService.selectOne(outboundPrepareLineWrapper);
                if (Objects.isNull(outboundPrepareLine)) {
                    resluts.add(detailDTO);
                }
            }
            if (CollectionUtils.isNotEmpty(resluts)) {
                for (PreparationListDetailDTO reslut : resluts) {
                    EntityWrapper<Sku> skuEW = new EntityWrapper<>();
                    skuEW.eq("lot_no1", reslut.getLotNo1()).orderBy("id", false);
                    Sku sku = skuService.selectOne(skuEW);
                    EntityWrapper<Stock> stcEW = new EntityWrapper<>();
                    if (sku != null) {
                        stcEW.eq("sku_id", sku.getId()).orderBy("id", false);
                        Stock stock = stockService.selectOne(stcEW);
                        if (stock != null) {
                            StoreLocation location = locationService.selectById(stock.getLocationId());
                            if (location != null) {
                                reslut.setLocationId(String.valueOf(location.getId()));
                                reslut.setLocationNo(location.getCode());
                            }
                        }
                    }
                }
                return resluts;
            }
        }
        if (CollectionUtils.isNotEmpty(detailDTOS)) {
            for (PreparationListDetailDTO detail : detailDTOS) {
                EntityWrapper<Sku> skuEW = new EntityWrapper<>();
                skuEW.eq("lot_no1", detail.getLotNo1())
                        .orderBy("id", false);
                Sku sku = skuService.selectOne(skuEW);
                EntityWrapper<Stock> stcEW = new EntityWrapper<>();
                if (sku != null) {
                    stcEW.eq("sku_id", sku.getId())
                            .orderBy("id", false);
                    Stock stock = stockService.selectOne(stcEW);
                    if (stock != null) {
                        StoreLocation location = locationService.selectById(stock.getLocationId());
                        if (location != null) {
                            detail.setLocationId(String.valueOf(location.getId()));
                            detail.setLocationNo(location.getCode());
                        }
                    }
                }
            }
            return detailDTOS;
        }
        return null;
    }

    /**
     * 备料任务变更   已出库不支持
     */
    @Override
    public void updateChangePreparation(OutboundPreparationParamDTO dto) {
        if (dto == null) {
            throw new BaseException("参数不能为空");
        }
        User loginUser = userService.getLoginUser();
        if (loginUser == null) {
            throw new BaseException("请登录后进行该操作");
        }
        String noticeHeadId = dto.getNoticeHeadId();
        String storeHouseId = dto.getStoreHouseId();
        if (StringUtils.isBlank(noticeHeadId)) {
            throw new BaseException("请选择需要变更的备料计划");
        }
        if (StringUtils.isBlank(storeHouseId)) {
            throw new BaseException("仓库id不能为空");
        }
        EntityWrapper<OutboundNoticeHeader> hlw = new EntityWrapper<>();
        hlw.eq("id", noticeHeadId);
        OutboundNoticeHeader noticeHeader = noticeHeaderService.selectById(noticeHeadId);
        if (noticeHeader == null) {
            throw new BaseException("未查询到通知单头Id:" + noticeHeadId + "的通知单信息");
        }

        //出库备料
        this.changePrepare(noticeHeadId, storeHouseId, loginUser, noticeHeader);

        //钥匙备料
        this.changeKeyPrepare(noticeHeadId, loginUser, noticeHeader);
    }

    /**
     * 钥匙-备料任务变更
     *
     * @param noticeHeadId 通知单详细id
     * @param loginUser    登录用户
     * @param noticeHeader 通知单头表
     */
    private void changeKeyPrepare(String noticeHeadId, User loginUser, OutboundNoticeHeader noticeHeader) {

        //查询备料头
        EntityWrapper<OutboundKeyPrepareHeader> phew = new EntityWrapper<>();
        phew.eq("notice_id", noticeHeadId);
        List<OutboundKeyPrepareHeader> prepareHeaders = keyPrepareHeaderMapper.selectList(phew);
        if (CollectionUtils.isEmpty(prepareHeaders)) {
            throw new BaseException("该通知单头ID:" + noticeHeadId + "还未生成备料");
        }
        OutboundKeyPrepareHeader prepareHeader = prepareHeaders.get(0);
        EntityWrapper<OutboundNoticeLine> llw = new EntityWrapper<>();
        llw.eq("header_id", noticeHeadId);
        List<OutboundNoticeLine> noticeLines = noticeLineService.selectList(llw);
        if (CollectionUtils.isNotEmpty(noticeLines)) {
            noticeLines.forEach(v -> {
                String nls = v.getStatus();
                if (TableStatusEnum.STATUS_50.getCode().equals(nls)) {
                    //看备料状态明细 如果是已完成  30,就不能调整为已取消。
                    EntityWrapper<OutboundKeyPrepareLine> plew = new EntityWrapper<>();
                    plew.eq("notice_line_id", v.getId());
                    List<OutboundKeyPrepareLine> prepareLines = keyPrepareLineMapper.selectList(plew);
                    if (CollectionUtils.isNotEmpty(prepareLines)) {
                        for (OutboundKeyPrepareLine pl : prepareLines) {
                            if (TableStatusEnum.STATUS_30.getCode().equals(pl.getStatus())) {
                                throw new BaseException("备料明细Id:" + pl.getId() + "已经进行过出库作业,请进行退库!");
                            }
                            pl.setStatus(TableStatusEnum.STATUS_40.getCode());
                            pl.setGmtModified(null);
                            keyPrepareLineService.updateById(pl);
                        }
                    }
                } else {
                    //看备料状态明细 如果没有明细就新增
                    EntityWrapper<OutboundKeyPrepareLine> plew = new EntityWrapper<>();
                    plew.eq("notice_line_id", v.getId());
                    List<OutboundKeyPrepareLine> prepareLines = keyPrepareLineService.selectList(plew);
                    if (CollectionUtils.isEmpty(prepareLines)) {
                        //新增明细
                        OutboundKeyPrepareLine prepareLine = new OutboundKeyPrepareLine();
                        BeanUtils.copyProperties(v, prepareLine);
                        prepareLine.setNoticeLineId(v.getId());
                        prepareLine.setStatus(TableStatusEnum.STATUS_10.getCode());
                        OutboundKeyPrepareLine pl = saveKeyPreparationLine(
                                new Date(),
                                v,
                                prepareHeader,
                                loginUser
                        );
                        pl.setShipSpace(prepareHeader.getLoadingArea());
                        keyPrepareLineService.insert(pl);
                        //通知单全部出库-->部分出库
                        if (TableStatusEnum.STATUS_30.getCode().equals(noticeHeader.getStatus())) {
                            noticeHeader.setStatus(TableStatusEnum.STATUS_20.getCode());
                            noticeHeader.setUserModified(loginUser.getName());
                            noticeHeaderService.updateById(noticeHeader);
                        }
                        if (TableStatusEnum.STATUS_40.getCode().equals(prepareHeader.getStatus())) {
                            prepareHeader.setStatus(TableStatusEnum.STATUS_30.getCode());
                        }
                        prepareHeader.setPlanSumQty(prepareHeader.getPlanSumQty());
                        prepareHeader.setLineCount(prepareHeader.getLineCount() + 1);
                        prepareHeader.setUserModified(loginUser.getName());
                        prepareHeader.setGmtModified(null);
                        keyPrepareHeaderMapper.updateById(prepareHeader);
                    }
                }
            });
        }
    }

    private void changePrepare(String noticeHeadId, String storeHouseId, User loginUser, OutboundNoticeHeader noticeHeader) {
        //查询备料头
        EntityWrapper<OutboundPrepareHeader> phew = new EntityWrapper<>();
        phew.eq("notice_id", noticeHeadId);
        List<OutboundPrepareHeader> prepareHeaders = baseMapper.selectList(phew);
        if (CollectionUtils.isEmpty(prepareHeaders)) {
            throw new BaseException("该通知单头ID:" + noticeHeadId + "还未生成备料");
        }
        OutboundPrepareHeader prepareHeader = prepareHeaders.get(0);
        EntityWrapper<OutboundNoticeLine> llw = new EntityWrapper<>();
        llw.eq("header_id", noticeHeadId);
        List<OutboundNoticeLine> noticeLines = noticeLineService.selectList(llw);
        if (CollectionUtils.isNotEmpty(noticeLines)) {
            noticeLines.forEach(v -> {
                String nls = v.getStatus();
                if (TableStatusEnum.STATUS_50.getCode().equals(nls)) {
                    //看备料状态明细 如果是已完成  30,就不能调整为已取消。
                    EntityWrapper<OutboundPrepareLine> plew = new EntityWrapper<>();
                    plew.eq("notice_line_id", v.getId());
                    List<OutboundPrepareLine> prepareLines = prepareLineService.selectList(plew);
                    if (CollectionUtils.isNotEmpty(prepareLines)) {
                        for (OutboundPrepareLine pl : prepareLines) {
                            if (TableStatusEnum.STATUS_30.getCode().equals(pl.getStatus())) {
                                //查看是否退车
                                EntityWrapper<OutboundShipLine> osEW = new EntityWrapper<>();
                                osEW.eq("notice_line_id", v.getId())
                                        .eq("is_quit", TableStatusEnum.STATUS_1.getCode());
                                int selectCount = shipLineService.selectCount(osEW);
                                if (selectCount == 0) {
                                    throw new BaseException("车辆" + pl.getLotNo1() + "已经进行过出库作业,请进行退库!");
                                }
                            }
                            pl.setStatus(TableStatusEnum.STATUS_40.getCode());
                            pl.setGmtModified(null);
                            prepareLineService.updateById(pl);
                        }
                    }
                } else {
                    //看备料状态明细 如果没有明细就新增
                    EntityWrapper<OutboundPrepareLine> plew = new EntityWrapper<>();
                    plew.eq("notice_line_id", v.getId());
                    List<OutboundPrepareLine> prepareLines = prepareLineService.selectList(plew);
                    if (CollectionUtils.isEmpty(prepareLines)) {
                        //新增明细
                        OutboundPrepareLine prepareLine = new OutboundPrepareLine();
                        BeanUtils.copyProperties(v, prepareLine);
                        prepareLine.setNoticeLineId(v.getId());
                        prepareLine.setStatus(TableStatusEnum.STATUS_10.getCode());
                        List<StockSkuToPrepareDTO> ssDTO = stockService.selectStockToPrepareByParams(v, Long.valueOf(storeHouseId));
                        if (CollectionUtils.isEmpty(ssDTO)) {
                            throw new BaseException("未查询到" + v.getLotNo1() + "的库存信息");
                        }
                        StockSkuToPrepareDTO stockSkuToPrepareDTO = ssDTO.get(0);
                        if ((stockSkuToPrepareDTO.getRemainQty().compareTo(v.getExpectQty())) < 0) {
                            throw new BaseException("库存id:" + stockSkuToPrepareDTO.getStockId() + "库存不足通知单数量出库");
                        }
                        OutboundPrepareLine pl = savePreparationLine(
                                loginUser,
                                new Date(),
                                v,
                                prepareHeader,
                                stockSkuToPrepareDTO);
                        pl.setShipSpace(prepareHeader.getLoadingArea());
                        prepareLineService.insert(pl);
                        //通知单全部出库-->部分出库
                        if (TableStatusEnum.STATUS_30.getCode().equals(noticeHeader.getStatus())) {
                            noticeHeader.setStatus(TableStatusEnum.STATUS_20.getCode());
                            noticeHeader.setUserModified(loginUser.getName());
                            noticeHeaderService.updateById(noticeHeader);
                        }
                        if (TableStatusEnum.STATUS_40.getCode().equals(prepareHeader.getStatus())) {
                            prepareHeader.setStatus(TableStatusEnum.STATUS_30.getCode());
                        }
                        prepareHeader.setPlanSumQty(prepareHeader.getPlanSumQty());
                        prepareHeader.setLineCount(prepareHeader.getLineCount() + 1);
                        prepareHeader.setUserModified(loginUser.getName());
                        prepareHeader.setGmtModified(null);
                        baseMapper.updateById(prepareHeader);
                    }
                }
            });
        }
    }


    @Override
    @Transactional
    public void updatePrepareFinishByLineId (Long noticeLineId, String modifiedName) {
        LOGGER.info("出库完成修改备料状态 noticeLineId ： {},修改用户：{}", noticeLineId, modifiedName);
        EntityWrapper<OutboundPrepareLine> plWp = new EntityWrapper<>();
        //过滤已取消
        plWp.eq("notice_line_id", noticeLineId);
        List<OutboundPrepareLine> opls = prepareLineService.selectList(plWp);
        LOGGER.info("查询出库备料数据结果  opls.size ： {}", opls.size());
        boolean isAllFinish = Boolean.TRUE;

        if (CollectionUtils.isNotEmpty(opls)) {
            OutboundPrepareLine prepareLine = opls.get(0);
            LOGGER.info("修改备料状态。。。。。。prepareLine.getId{}",prepareLine.getId());
            prepareLine.setFinishTime(new Date());
            prepareLine.setStatus(TableStatusEnum.STATUS_30.getCode());
            prepareLine.setActualQty(prepareLine.getPlanQty());
            prepareLine.setGmtModified(null);
            prepareLineService.updateById(prepareLine);
            //判断头状态
            OutboundPrepareHeader prepareHeader = selectById(prepareLine.getHeaderId());
            if (prepareHeader != null) {
                EntityWrapper<OutboundPrepareLine> ew = new EntityWrapper<>();
                ew.eq("header_id", prepareHeader.getId())
                        .notIn("status", TableStatusEnum.STATUS_40.getCode());
                List<OutboundPrepareLine> lines = prepareLineService.selectList(ew);
                for (OutboundPrepareLine line : lines) {
                    if (!TableStatusEnum.STATUS_30.getCode().equals(line.getStatus())) {
                        isAllFinish = Boolean.FALSE;
                        break;
                    }
                }
                if (isAllFinish) {
                    prepareHeader.setFinishTime(new Date());
                    prepareHeader.setStatus(TableStatusEnum.STATUS_40.getCode());
                } else {
                    prepareHeader.setStatus(TableStatusEnum.STATUS_30.getCode());
                }
                prepareHeader.setUserModified(modifiedName);
                prepareHeader.setGmtModified(null);
                updateById(prepareHeader);
            }
        }
    }

    private OutboundPrepareLine savePreparationLine(User loginUser,
                                                    Date finalPt,
                                                    OutboundNoticeLine nl,
                                                    OutboundPrepareHeader ph,
                                                    StockSkuToPrepareDTO stock) {
        OutboundPrepareLine pl = new OutboundPrepareLine();
        BeanUtils.copyProperties(nl, pl);
        pl.setId(snowFlakeId.nextId());
        pl.setHeaderId(ph.getId());
        pl.setNoticeLineId(nl.getId());
        pl.setLocationId(stock.getLocationId());
        pl.setStockId(stock.getStockId());
        StoreLocation storeLocation = locationService.selectById(stock.getLocationId());
        if (storeLocation != null) {
            pl.setLocationNo(storeLocation.getCode());
        }
        pl.setPlanQty(nl.getExpectQty());
        pl.setActualQty(new BigDecimal("0"));
        pl.setPlanTime(finalPt);
        pl.setStatus(TableStatusEnum.STATUS_10.getCode());
        return pl;
    }

    private OutboundPrepareHeader savePreparationHead(User loginUser,
                                                      Date finalPt,
                                                      OutboundNoticeHeader nh) {
        OutboundPrepareHeader ph = new OutboundPrepareHeader();
        BeanUtils.copyProperties(nh, ph);
        ph.setId(snowFlakeId.nextId());
        ph.setNoticeId(nh.getId());
        ph.setPrepareNo(docNumberService.getOutboundPrepareNo());
        ph.setOrderTime(new Date());
        ph.setPlanTime(finalPt);
        ph.setStatus(TableStatusEnum.STATUS_20.getCode());
        ph.setUserCreate(loginUser.getName());
        ph.setUserModified(loginUser.getName());
        return ph;
    }

    private OutboundKeyPrepareHeader saveKeyPreparationHead(User loginUser,
                                                            Date finalPt,
                                                            OutboundNoticeHeader nh) {
        OutboundKeyPrepareHeader ph = new OutboundKeyPrepareHeader();
        BeanUtils.copyProperties(nh, ph);
        ph.setId(snowFlakeId.nextId());
        ph.setNoticeId(nh.getId());
        ph.setPrepareNo(docNumberService.getOutboundPrepareNo());
        ph.setOrderTime(new Date());
        ph.setPlanTime(finalPt);
        ph.setStatus(TableStatusEnum.STATUS_10.getCode());
        ph.setUserCreate(loginUser.getName());
        ph.setUserModified(loginUser.getName());
        return ph;
    }

    private Map<String, Object> checkAndSetParams(OutboundPreparationParamDTO dto) {
        String preparationStatus = dto.getPreparationStatus();
        String outShipStatus = dto.getOutShipStatus();
        String headSourceNo = dto.getHeadSourceNo();
        String headSourceKey = dto.getHeadSourceKey();
        String startTime = dto.getStartTime();
        String endTime = dto.getEndTime();
        String noticeHeadNo = dto.getNoticeHeadNo();
        String ownerOrderNo = dto.getOwnerOrderNo();
        Map<String, Object> params = Maps.newHashMap();
        params.put("start", dto.getStartIndex());
        params.put("end", dto.getPageSize());
        params.put("orderBy", "b.gmt_create desc,b.id ASC");
        if (StringUtils.isNotBlank(preparationStatus)) {
            if (TableStatusEnum.STATUS_10.getCode().equals(preparationStatus)) {
                params.put("preparationStatus", "and (d.status = '" + preparationStatus + "' or d.status is null)");
            } else {
                params.put("preparationStatus", "and d.status = " + preparationStatus);
            }
        }
        if (StringUtils.isNotBlank(ownerOrderNo)) {
            params.put("ownerOrderNo", ownerOrderNo);
        }
        if (StringUtils.isNotBlank(noticeHeadNo)) {
            params.put("noticeHeadNo", noticeHeadNo);
        }
        if (StringUtils.isNotBlank(outShipStatus)) {
            params.put("outShipStatus", outShipStatus);
        }
        if (StringUtils.isNotBlank(headSourceNo)) {
            params.put("headSourceNo", headSourceNo);
        }
        if (StringUtils.isNotBlank(headSourceKey)) {
            params.put("headSourceKey", headSourceKey);
        }
        if (StringUtils.isNotBlank(startTime)) {
            params.put("startTime", startTime + " 00:00:00");
        }
        if (StringUtils.isNotBlank(endTime)) {
            params.put("endTime", endTime + " 23:59:59");
        }
        return params;
    }

    @Override
    public Page<PreparationListHeadDTO> notPreparationList(Page<PreparationListHeadDTO> page) {
        baseMapper.updateSQLMode();
        Wrapper<PreparationListHeadDTO> wp = buildWrapper(page, TableStatusEnum.STATUS_1.getCode());
        List<PreparationListHeadDTO> records = baseMapper.queryNotOutPreparePage(page, wp);
        page.setRecords(records);
        return page;
    }

    /**
     * 基于板车纬度展示备料信息
     * searchLabel 10:待领取  20:执行中
     */
    @Override
    public Page<OutboundPrepareVehicleDTO> getPrepareVehicle(Page<OutboundPrepareVehicleDTO> page) {
        LOGGER.info("OutboundPrepareHeaderServiceImpl.getPrepareVehicle param:{}", JSONObject.toJSONString(page.getCondition()));
        if (page == null) {
            throw new BaseException("参数不能为空");
        }
        Map<String, Object> con = page.getCondition();
        if (con == null || con.isEmpty()) {
            throw new BaseException("condition不能为空");
        }
        if (Objects.isNull(con.get("searchLabel"))
                || StringUtils.isBlank(con.get("searchLabel").toString())) {
            throw new BaseException("查询分类不能为空");
        }
        if (Objects.isNull(con.get("houseId"))
                || StringUtils.isBlank(con.get("houseId").toString())) {
            throw new BaseException("仓库id不能为空");
        }
        EntityWrapper<OutboundPrepareHeader> phEW = new EntityWrapper<>();
        phEW.eq("c.store_house_id", con.get("houseId").toString());
        if (TableStatusEnum.STATUS_10.getCode().equals(con.get("searchLabel").toString())) {
            //待领取
            phEW.eq("a.status", TableStatusEnum.STATUS_20.getCode());
        }
        if (TableStatusEnum.STATUS_20.getCode().equals(con.get("searchLabel").toString())) {
            phEW.eq("a.user_modified", userService.getLoginUser().getName())
                    .eq("a.status", TableStatusEnum.STATUS_30.getCode());
        }
        if (!Objects.isNull(con.get("plateNo")) && StringUtils.isNotEmpty(con.get("plateNo").toString())) {
            phEW.andNew().like("a.plate_number", con.get("plateNo").toString()).or().like("b.shipment_gid",con.get("plateNo").toString());
        }
        phEW.andNew().ne("b.status", TableStatusEnum.STATUS_50.getCode()).or().isNull("b.status");
        phEW.orderBy("a.gmt_modified", false);
        phEW.orderBy("a.id", false);
        List<OutboundPrepareVehicleDTO> records = baseMapper.queryPrepareVehiclePage(page, phEW);
        page.setRecords(records);
        return page;
    }

    @Override
    public Page<PreparationListHeadDTO> queryOutKeyPreparePage (Page<PreparationListHeadDTO> page) {
        if (page == null) {
            throw new BaseException("参数不能为空");
        }
        Map cd = page.getCondition();
        Wrapper<PreparationListHeadDTO> wp = new EntityWrapper<>();
        if (cd != null) {
            if (StringUtils.isBlank((String) cd.get("storeHouseId"))) {
                throw new BaseException("仓库不能为空");
            } else {
                wp.eq("houseId", cd.get("storeHouseId").toString());
            }
            if (cd.containsKey("preparationStatus") && StringUtils.isNotEmpty((String)cd.get("preparationStatus"))) {
                wp.eq("prepareStatus", cd.get("preparationStatus").toString());
            }
            if (cd.containsKey("ownerOrderNo") && StringUtils.isNotEmpty((String)cd.get("ownerOrderNo"))) {
                wp.eq("owner_order_no", cd.get("ownerOrderNo").toString());
            }
            if (cd.containsKey("plateNumber") && StringUtils.isNotEmpty((String) cd.get("plateNumber"))) {
                wp.eq("plate_no", page.getCondition().get("plateNumber"));
            }
            if (cd.containsKey("outShipStatus") && StringUtils.isNotEmpty((String)cd.get("outShipStatus"))) {
                wp.eq("noticeHeadStatus", cd.get("outShipStatus").toString());
            }
            if (cd.containsKey("startDate") && StringUtils.isNotEmpty((String) cd.get("startDate"))) {
                wp.ge("shipmentCreate", cd.get("startDate").toString());
            }
            if (cd.containsKey("endDate") && StringUtils.isNotEmpty((String) cd.get("endDate"))) {
                wp.le("shipmentCreate", cd.get("endDate").toString());
            }
            if (cd.containsKey("lotNo1") && StringUtils.isNotEmpty((String)cd.get("lotNo1"))) {
                EntityWrapper<OutboundNoticeLine> nlEW = new EntityWrapper<>();
                List<String> vins = Arrays.asList(CommonMethod.setVins(cd.get("lotNo1").toString()));
                nlEW.ne("status", TableStatusEnum.STATUS_50.getCode());
                nlEW.andNew().in("lot_no1", vins).or().like("lot_no1", cd.get("lotNo1").toString());
                List<OutboundNoticeLine> noticeLines = noticeLineService.selectList(nlEW);
                ArrayList<Long> ids = Lists.newArrayList();
                for (OutboundNoticeLine line : noticeLines) {
                    ids.add(line.getHeaderId());
                }
                wp.in("noticeHeadId", ids);
            }
        }
        wp.orderBy("prepareHeaderCreate", Boolean.FALSE);
        wp.orderBy("owner_order_no", Boolean.TRUE);
        List<PreparationListHeadDTO> records = baseMapper.queryOutKeyPreparePage(page, wp, cd.get("storeHouseId").toString());
        page.setRecords(records);
        return page;
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public void singlePreparation(OutboundPreparationParamDTO dto) {
        if (dto == null) {
            throw new BaseException("参数不能为空!");
        }
        if (StringUtils.isBlank(dto.getPrepareLane())) {
            throw new BaseException("请填写备料装车道");
        }
        if (StringUtils.isBlank(dto.getPlanTime())) {
            throw new BaseException("计划备料时间不能为空");
        }
        if (StringUtils.isBlank(dto.getNoticeHeadId())) {
            throw new BaseException("请选择需要创建备料任务的数据");
        }
        if (dto.getLineIds().length <= 0) {
            throw new BaseException("请选择需要单台备料任务的数据");
        }
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date pt = null;
        try {
            pt = sdf.parse(dto.getPlanTime());
        } catch (ParseException e) {
            throw new BaseException("日期" + dto.getPlanTime() + "转换异常");
        }

        User loginUser = userService.getLoginUser();
        if (loginUser == null) {
            throw new BaseException("请登录后进行该操作");
        }
        OutboundNoticeHeader noticeHeader = noticeHeaderService.selectById(dto.getNoticeHeadId());
        String[] lineIds = dto.getLineIds();

        this.singleprepare(pt, loginUser, noticeHeader, lineIds, dto);
        this.keySingleprepare(pt, loginUser, noticeHeader, lineIds, dto);
    }

    /**
     * 单台车辆备料钥匙
     *
     * @param pt           备料时间
     * @param loginUser    登录用户
     * @param noticeHeader 通知头
     * @param lineIds      通知id
     * @param dto          入参
     */
    private void keySingleprepare(Date pt, User loginUser, OutboundNoticeHeader noticeHeader, String[] lineIds, OutboundPreparationParamDTO dto) {
        ArrayList<OutboundKeyPrepareLine> ipls = Lists.newArrayList();
        OutboundKeyPrepareHeader ph = saveKeyPreparationHead(loginUser, pt, noticeHeader);
        ph.setPlanSumQty(new BigDecimal(0));
        ph.setLineCount(0);
        ph.setLoadingArea(dto.getPrepareLane());
        //单台备料生成一个明细一个头
        for (String lineId : lineIds) {
            Wrapper<OutboundKeyPrepareLine> keypreparelineParams = new EntityWrapper<>();
            keypreparelineParams.eq("notice_line_id", lineId);
            int count = keyPrepareLineService.selectCount(keypreparelineParams);
            if (count > 0) {
                throw new BaseException("该明细已进行过单台备料");
            }
            EntityWrapper<OutboundNoticeLine> nlw = new EntityWrapper<>();
            nlw.eq("id", lineId).eq("status", TableStatusEnum.STATUS_10.getCode());
            OutboundNoticeLine outboundNoticeLine = noticeLineService.selectOne(nlw);
            if (Objects.isNull(outboundNoticeLine)) {
                throw new BaseException("未查询到通知单" + outboundNoticeLine.getLotNo1() + "的出库通知单信息");
            }
            OutboundKeyPrepareLine pl = saveKeyPreparationLine(pt, outboundNoticeLine, ph, loginUser);
            pl.setShipSpace(dto.getPrepareLane());
            ph.setPlanSumQty(ph.getPlanSumQty().add(pl.getPlanQty()));
            ph.setLineCount(ph.getLineCount() + 1);
            ipls.add(pl);
        }
        //头
        if (CollectionUtils.isNotEmpty(ipls)) {
            keyPrepareHeaderMapper.insert(ph);
            for (OutboundKeyPrepareLine outboundKeyPrepareLine : ipls){
                keyPrepareLineService.insert(outboundKeyPrepareLine);
            }
        }
    }

    /**
     * 单台车辆备料
     *
     * @param pt           备料时间
     * @param loginUser    登录用户
     * @param noticeHeader 通知头
     * @param lineIds      通知id
     * @param dto          入参
     */
    private void singleprepare(Date pt, User loginUser, OutboundNoticeHeader noticeHeader, String[] lineIds, OutboundPreparationParamDTO dto) {
        ArrayList<OutboundPrepareLine> ipls = Lists.newArrayList();
        OutboundPrepareHeader ph = savePreparationHead(loginUser, pt, noticeHeader);
        ph.setPlanSumQty(new BigDecimal(0));
        ph.setLineCount(0);
        ph.setLoadingArea(dto.getPrepareLane());
        //单台备料生成一个明细一个头
        for (String lineId : lineIds) {
            Wrapper<OutboundPrepareLine> outboundPrepareLineWrapper = new EntityWrapper<>();
            outboundPrepareLineWrapper.eq("notice_line_id", lineId);
            int count = prepareLineService.selectCount(outboundPrepareLineWrapper);
            if (count > 0) {
                throw new BaseException("该明细已进行过单台备料");
            }
            EntityWrapper<OutboundNoticeLine> nlw = new EntityWrapper<>();
            nlw.eq("id", lineId)
                    .eq("status", TableStatusEnum.STATUS_10.getCode());
            OutboundNoticeLine outboundNoticeLine = noticeLineService.selectOne(nlw);
            if (Objects.isNull(outboundNoticeLine)) {
                throw new BaseException("未查询到出库通知单信息");
            }

            //查询库存
            Integer stockCount = stockMapper.queryStockPrepare(outboundNoticeLine.getLotNo1(), noticeHeader.getStoreHouseId());
            if (stockCount == 0) {
                throw new BaseException("未查询到车架号:" + outboundNoticeLine.getLotNo1() + "库存信息");
            }

            List<StockSkuToPrepareDTO> list = stockService.selectStockToPrepareByParams(outboundNoticeLine, noticeHeader.getStoreHouseId());
            if (CollectionUtils.isEmpty(list)) {
                LOGGER.info("未查询到NoticeLineId{}库存信息", outboundNoticeLine.getId());

                EntityWrapper<OutboundNoticeHeader> hEw = new EntityWrapper<>();
                hEw.eq("opl.lot_no1", outboundNoticeLine.getLotNo1());
                hEw.eq("onh.store_house_id", noticeHeader.getStoreHouseId());
                hEw.isNotNull("opl.id");
                List<OutboundNoticeHeader> outboundNoticeHeader = outboundNoticeHeaderMapper.queryPrepareShipment(hEw);
                if (CollectionUtils.isNotEmpty(outboundNoticeHeader)) {
                    throw new BaseException("车辆［" + outboundNoticeLine.getLotNo1() + "］曾经在指令［" + outboundNoticeHeader.get(0).getSourceKey() + "] " +
                            "中备料未出库，请在“已备料列表”中根据指令号查询后对该车辆操作“备料任务变更“");
                } else {
                    throw new BaseException("车辆［" + outboundNoticeLine.getLotNo1() + "］已有备料信息，请在“已备料列表”中根据指令号查询后对该车辆操作“备料任务变更“");
                }
            }
            StockSkuToPrepareDTO stockSkuToPrepareDTO = list.get(0);
            if ((stockSkuToPrepareDTO.getRemainQty().compareTo(outboundNoticeLine.getExpectQty())) < 0) {
                LOGGER.info("库存id:{}库存不足通知单数量出库" + stockSkuToPrepareDTO.getStockId());
                throw new BaseException("车架号:" + stockSkuToPrepareDTO.getLotNo1() + "库存不足通知单数量出库");
            }
            OutboundPrepareLine pl = savePreparationLine(
                    loginUser,
                    pt,
                    outboundNoticeLine,
                    ph,
                    stockSkuToPrepareDTO);
            pl.setShipSpace(dto.getPrepareLane());
            ph.setPlanSumQty(ph.getPlanSumQty().add(pl.getPlanQty()));
            ph.setLineCount(ph.getLineCount() + 1);
            ipls.add(pl);
        }
        //头
        if (CollectionUtils.isNotEmpty(ipls)) {
            insert(ph);
            prepareLineService.insertBatch(ipls);
        }
    }

    @Override
    public List<PreparationListDetailDTO> getKeyPrepareDetail(OutboundPreparationParamDTO dto) {
        if (dto == null) {
            throw new BaseException("参数不能为空");
        }
        String noticeHeadId = dto.getNoticeHeadId();
        if (StringUtils.isEmpty(noticeHeadId)) {
            throw new BaseException("通知单【noticeHeadId】不能为空");
        }
        if (StringUtils.isEmpty(dto.getHeadId())) {
            throw new BaseException("【headId】不能为空");
        }
        HashMap<String, Object> params = Maps.newHashMap();
        params.put("noticeHeadId", noticeHeadId);
        params.put("headId", dto.getHeadId());
        params.put("groupBy", "lineId");
        params.put("orderBy", "a.gmt_modified desc");
        keyPrepareHeaderMapper.updateSQLMode();
        List<PreparationListDetailDTO> detailDTOS = keyPrepareHeaderMapper.selectKeyPrepareDetailListByParams(params);
        List<PreparationListDetailDTO> resluts = new ArrayList<>();
        if (StringUtils.isEmpty(dto.getHeadId())) {
            for (PreparationListDetailDTO prepareDetailDTO : detailDTOS) {
                Wrapper<OutboundKeyPrepareLine> outPrepareLineEw = new EntityWrapper<>();
                outPrepareLineEw.eq("notice_line_id", prepareDetailDTO.getLineId());
                OutboundKeyPrepareLine outKeyPrepareLine = keyPrepareLineService.selectOne(outPrepareLineEw);
                if (Objects.isNull(outKeyPrepareLine)) {
                    resluts.add(prepareDetailDTO);
                }
            }
            if (CollectionUtils.isNotEmpty(resluts)) {
                for (PreparationListDetailDTO reslut : resluts) {
                    EntityWrapper<Sku> skuEntityWrapper = new EntityWrapper<>();
                    skuEntityWrapper.eq("lot_no1", reslut.getLotNo1()).orderBy("id", false);
                    Sku sku = skuService.selectOne(skuEntityWrapper);
                    if (null != sku) {
                        EntityWrapper<Stock> stcEW = new EntityWrapper<>();
                        stcEW.eq("sku_id", sku.getId()).eq("store_house_id", reslut.getStoreHouseId()).orderBy("id", false);
                        Stock stock = stockService.selectOne(stcEW);
                        if (null != stock) {
                            StoreLocation location = locationService.selectById(stock.getLocationId());
                            if (null != location) {
                                reslut.setLocationId(String.valueOf(location.getId()));
                                reslut.setLocationNo(location.getCode());
                                reslut.setStockProperty(stock.getStockProperty());
                            }
                        }
                    }
                }
                return resluts;
            }
        }
        if (!CollectionUtils.isEmpty(detailDTOS)) {
            for (PreparationListDetailDTO detail : detailDTOS) {
                EntityWrapper<Sku> skuEW = new EntityWrapper<>();
                skuEW.eq("lot_no1", detail.getLotNo1()).orderBy("id", false);
                Sku sku = skuService.selectOne(skuEW);
                if (null != sku) {
                    EntityWrapper<Stock> stcEW = new EntityWrapper<>();
                    stcEW.eq("sku_id", sku.getId()).eq("store_house_id", detail.getStoreHouseId()).orderBy("id", false);
                    Stock stock = stockService.selectOne(stcEW);
                    if (null != stock) {
                        StoreLocation location = locationService.selectById(stock.getLocationId());
                        if (null != location) {
                            detail.setLocationId(String.valueOf(location.getId()));
                            detail.setLocationNo(location.getCode());
                            detail.setStockProperty(stock.getStockProperty());
                        }
                    }
                }
            }
            return detailDTOS;
        }
        return detailDTOS;
    }

    @Override
    @Transactional
    public void updateKeyPrepareStatus(Map<String, String> param) {
        User loginUser = userService.getLoginUser();
        if (loginUser == null) {
            throw new BaseException("请登录后进行该操作");
        }
        String keyParam = param.get("key");
        if (StringUtils.isEmpty(keyParam)) {
            throw new BaseException("参数【key】为空，请重新确认！");
        }
        String[] keys = keyParam.split(",");
        //根据key修改头表的状态为20：开始执行
        this.updateKeyHeaderStatus(keys[0], loginUser.getName());
        for (String key : keys) {
            //是否存在数据或者是否已经备料过
            this.isExistKeyPrepare(key);
            OutboundKeyPrepareLine keyPrepareLine = new OutboundKeyPrepareLine();
            keyPrepareLine.setStatus(TableStatusEnum.STATUS_20.getCode());
            Wrapper<OutboundKeyPrepareLine> ew = new EntityWrapper<>();
            ew.eq("id", key);
            ew.eq("status", TableStatusEnum.STATUS_10.getCode());
            keyPrepareLineMapper.update(keyPrepareLine, ew);
        }
    }

    @Override
    public List<PreparationPrintDTO> queryKeyPerparePrintData (Map<String, String> params) {
        if (Objects.isNull(params)){
            throw new BaseException("入参不能为空");
        }
        if(Objects.isNull(params.get("headId")) && StringUtils.isEmpty(params.get("headId"))){
            throw new BaseException("入参【headId】不能为空");
        }
        String headId = params.get("headId");
        String[] headIds = headId.split(",");
        List<String> printHeadIds = Arrays.asList(headIds);
        Wrapper<PreparationPrintDTO> ew = new EntityWrapper<>();
        ew.in("okpl.id",printHeadIds);
        ew.orderBy("okpl.gmt_create",false);
        List<PreparationPrintDTO> list = keyPrepareLineMapper.queryKeyPerparePrintData(ew);
        return list;
    }

    @Override
    public List<BatchPrintPrepare> batchPrintPrepare (Map<String, String> params) {
        if (null == params || params.isEmpty()) {
            throw new BaseException("入参不能为空!");
        }
        String headId = params.get("headIds");
        if (StringUtils.isEmpty(headId)) {
            throw new BaseException("参数【headIds】不能为空！");
        }

        String[] headIds = headId.split(",");
        EntityWrapper<BatchPrintPrepare> headEw = new EntityWrapper<>();
        headEw.in("wkh.id", Arrays.asList(headIds));
        List<BatchPrintPrepare> batchPrintPrepares = keyPrepareLineMapper.batchPrintPrepareHeader(headEw);
        if (CollectionUtils.isNotEmpty(batchPrintPrepares)) {
            for (BatchPrintPrepare batchPrintPrepare : batchPrintPrepares) {
                EntityWrapper<PreparePrintDetail> detailEw = new EntityWrapper<>();
                detailEw.eq("okl.header_id", batchPrintPrepare.getHeadId());
                List<PreparePrintDetail> preparePrintDetails = keyPrepareLineMapper.queryPreparePrintDetail(detailEw);
                batchPrintPrepare.setPreparePrintDetail(preparePrintDetails);
            }
        }
        return batchPrintPrepares;
    }

    @Override
    public void confirmPrepare (List<BatchPrintPrepare> param) {
        User loginUser = userService.getLoginUser();
        if (loginUser == null) {
            throw new BaseException("请登录后进行该操作");
        }
        if (CollectionUtils.isEmpty(param)) {
            throw new BaseException("备料明细为空，请重新确认");
        }

        for (BatchPrintPrepare batchPrintPrepare : param) {
            //根据key修改头表的状态为20：开始执行
            OutboundKeyPrepareHeader headParam = new OutboundKeyPrepareHeader();
            headParam.setStatus(TableStatusEnum.STATUS_20.getCode());
            headParam.setStartTime(new Date());
            headParam.setGmtModified(new Date());
            headParam.setUserModified(loginUser.getName());
            Wrapper<OutboundKeyPrepareHeader> ew = new EntityWrapper<>();
            ew.eq("status", TableStatusEnum.STATUS_10.getCode());
            ew.eq("id", batchPrintPrepare.getHeadId());
            keyPrepareHeaderMapper.update(headParam, ew);
            for (PreparePrintDetail preparePrintDetail : batchPrintPrepare.getPreparePrintDetail()) {
                OutboundKeyPrepareLine keyPrepareLine = new OutboundKeyPrepareLine();
                keyPrepareLine.setStatus(TableStatusEnum.STATUS_20.getCode());
                Wrapper<OutboundKeyPrepareLine> prepareLineEw = new EntityWrapper<>();
                prepareLineEw.eq("id", preparePrintDetail.getKeyPrepareId());
                prepareLineEw.eq("status", TableStatusEnum.STATUS_10.getCode());
                keyPrepareLineMapper.update(keyPrepareLine, prepareLineEw);
            }
        }
    }

    private void isExistKeyPrepare(String key) {
        OutboundKeyPrepareLine lineResult = keyPrepareLineMapper.selectById(key);
        if (null == lineResult) {
            throw new BaseException("没有【" + lineResult.getLotNo1() + "】数据的明细信息，请重新确认参数是否正确");
        }
        Wrapper<OutboundKeyPrepareLine> ew = new EntityWrapper<>();
        ew.eq("id", key);
        ew.eq("status", TableStatusEnum.STATUS_20.getCode());
        List<OutboundKeyPrepareLine> list = keyPrepareLineMapper.selectList(ew);
        if (CollectionUtils.isNotEmpty(list)) {
            throw new BaseException(list.get(0).getLotNo1() + "已经确认过备料，请重新选择数据");
        }
    }

    private void updateKeyHeaderStatus(String key, String name) {
        OutboundKeyPrepareLine lineResult = keyPrepareLineMapper.selectById(key);
        if (null != lineResult) {
            Long heardId = lineResult.getHeaderId();
            OutboundKeyPrepareHeader param = new OutboundKeyPrepareHeader();
            param.setStatus(TableStatusEnum.STATUS_20.getCode());
            param.setStartTime(new Date());
            param.setGmtModified(new Date());
            param.setUserModified(name);
            Wrapper<OutboundKeyPrepareHeader> ew = new EntityWrapper<>();
            ew.eq("status", TableStatusEnum.STATUS_10.getCode());
            ew.eq("id", heardId);
            keyPrepareHeaderMapper.update(param, ew);
        }

    }
}
